#pragma
#include <string>
#include <vector>
#include <cstdio> 
#include <cerrno>
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>

#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;
const char* pathname = "/home/yangbiao/linux_code/shm_ipc";
const int project_id = 666;
// 在内核中的,共享内存的大小是以4kb为单位的.所以建议的申请大小是n*4kb
const int defaultsize = 4096; 
key_t GetShmKeyOrDie()
{
    key_t key = ftok(pathname,project_id);
    if(key == -1)
    {
        perror("ftok");
        cout<<"errno:"<<errno<<endl;
        exit(1);
    }
    return key;
}
// 将key转化成为16进制.
string ToHex(key_t key)
{
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"0x%x",key);
    return string(buffer);
}

// 创建共享内存
int CreateShmOrDie(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid<0)
    {
        perror("shmget");
        exit(1);
    }
    return shmid;
}

int CreateShm(key_t key,int size)
{
    return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}

int GetShm(key_t key,int size)
{
    // IPC_CREAT表示如果共享内存存在,就获取,若不存在就创建.
    return CreateShmOrDie(key,size,IPC_CREAT);
}
void DeleteShm(int shmid)
{   
    int ret = shmctl(shmid,IPC_RMID,NULL);
    if(ret<0){
        perror("shmctl");
    }
    else{
        cout<<"delete shm success!"<<endl;
    }
}

void ShmDebug(int shmid)
{
    struct  shmid_ds ds;
    int ret = shmctl(shmid,IPC_STAT,&ds);
    if(ret<0)
    {
        perror("shmctl");
    }
    cout<<"shm_cpid:"<<ds.shm_cpid<<endl;
    cout<<"shm_lpid:"<<ds.shm_lpid<<endl;
    cout<<"shm_nattch:"<<ds.shm_nattch<<endl;
    cout<<"key:"<<ToHex(ds.shm_perm.__key)<<endl; 
}

void* ShmAttach(int shmid)  
{
    void* addr = shmat(shmid,nullptr,0);
    if((long long int)addr==-1){
        cout<<"attach fail"<<endl;
        return nullptr;
    }
    return addr;
}
int ShmDetach(void* addr)
{
    int n = shmdt(addr);
    if(n==-1){
        cout<<"de error!!"<<endl;
    }
    return n;
}


